home *** CD-ROM | disk | FTP | other *** search
-
- (c) Copyright 1992 Commodore-Amiga, Inc. All rights reserved. The
- information contained herein is subject to change without notice, and
- is provided "as is" without warranty of any kind, either expressed or
- implied. The entire risk as to the use of this information is
- assumed by the user.
-
-
- Fast AmigaDOS I/O
-
-
- by Martin Taillefer
-
- Reading and writing data is crucial to most applications and is, in
- many cases, a major bottleneck. Using the Amiga's sophisticated file
- system architecture can help reduce, and sometimes eliminate, the
- time spent waiting for I/O to complete. This article presents six
- small routines that can greatly improve an application's I/O
- performance.
-
- Typically, an application processes a file in the following manner:
-
- Step 1: Open the file.
-
- Step 2: Read some data (with the DOS library's Read() function).
-
- Step 3: Process that data.
-
- Step 4: Repeat steps 2 and 3 until the application is finished
- processing the file.
-
- Step 5: Close file.
-
- This sequence of steps is effective, but it does have a potential
- bottleneck. Whenever the application reads some data using the DOS
- Read() function, the Amiga has to put that task to sleep and ask the
- file system to fetch the data. The file system then starts up the
- disk hardware and reads the data. After the file system finishes
- reading the data, the operating system wakes up the application.
-
- The problem is step 2. While the file system is busy reading data
- from the disk, the application is idle, waiting for the DOS I/O in
- Read() to complete. A more sophisticated application would initiate
- an asynchronous read, allowing the application to continue to do some
- other important chore while the file system is busy reading. If all
- goes well, the file system will be finished with the asynchronous
- read by the time the application is finished with its chore, so the
- application will not have to wait for any DOS I/O to complete before
- the application can access data.
-
-
- Using the routines presented in this article, an application
- processes a file in the following manner:
-
- Step 1: Open the file with OpenAsync(). This function opens the
- file and, if the file is opened for reading, OpenAsync() asks the
- file system to start reading data, asynchronously.
-
- Step 2: Read some data with ReadAsync(). If the asynchronous read
- request that OpenAsync() sent has not completed, ReadAsync() will
- put the application to sleep until that request returns. Ideally,
- the read will have returned, so the application won't have to wait.
- ReadAsync() will also initiate a new asynchronous read so new file
- data is ready when the application needs it.
-
- Step 3: Process the file data.
-
- Step 4: Repeat steps 2 and 3 until the application processes all its
- file data.
-
- Step 5: Close the file with CloseAsync().
-
- Immediately after opening the file, OpenAsync() sends a request to
- the file system to get it reading data in the background. If all
- goes well, by the time the application gets around to reading the
- first byte of data, the file system has already copied the data into
- memory. That means the application doesn't need to wait and can
- immediately start processing the data. As soon as the application
- starts processing data from the file using ReadAsync(), ReadAsync()
- sends out a second request to the file system to fill up a second
- buffer. Once the application is done processing the first buffer, it
- starts processing the second one. When this happens, the file system
- starts filling up the first buffer again with new data. This process
- continues until the application has read all of its data. This
- technique is known as ``double-buffered asynchronous I/O''.
-
- The set of functions presented below offer high-performance I/O using
- the technique described above. The interface is very similar to
- standard AmigaDOS files. These routines enable full asynchronous
- read/write of any file.
-
- These functions are especially useful on an Amiga with a DMA (Direct
- Memory Access) hard drive. DMA makes it possible to transfer data to
- memory at the same time the CPU is busy executing a task's
- instructions. A DMA data transfer is truly parallel, so, under
- normal conditions, the CPU is operating at full speed, unaffected by
- the DMA transfer. This parallelism is what makes the set of
- accompanying routines so efficient. They exploit the fact that the
- Amiga can transfer an application's data while the application is
- busy processing other data.
-
- Although these asynchronous routines make disk I/O much faster, they
- do have an important limitation. The routines do not support seeking
- into a file.
-
-
-
-
-
-
- TABLE OF CONTENTS
-
- asyncio/CloseAsync
- asyncio/OpenAsync
- asyncio/ReadAsync
- asyncio/ReadAsyncChar
- asyncio/WriteAsync
- asyncio/WriteAsyncChar
-
-
- asyncio/CloseAsync asyncio/CloseAsync
-
- NAME
- CloseAsync -- close an async io file.
-
- SYNOPSIS
- result = CloseAsync(file);
-
- LONG CloseAsync(struct AsyncFile *);
-
- FUNCTION
- Closes a file, flushing any pending writes. Once this call has been
- made, the file can no longer be accessed.
-
- INPUTS
- file - the file to close. May be NULL.
-
- RESULT
- result - < 0 for an error, >= 0 for success. Indicates whether closing
- the file worked or not. If the file was opened in read-mode,
- then this call will always work. In case of error,
- dos.library/IoErr() can give more information.
-
- SEE ALSO
- OpenAsync, dos.library/Close()
-
-
- asyncio/OpenAsync asyncio/OpenAsync
-
- NAME
- OpenAsync -- open a file for asynchronous IO.
-
- SYNOPSIS
- file = OpenAsync(fileName, accessMode, bufferSize);
-
- struct AsyncFile OpenAsync(STRPTR, UBYTE, LONG);
-
- FUNCTION
- The named file is opened and an async file handle returned. If the
- accessMode is MODE_READ, an existing file is opened for reading.
- If the value is MODE_WRITE, a new file is created for writing. If
- a file of the same name already exists, it is first deleted. If
- accessMode is MODE_APPEND, an existing file is prepared for writing.
- Data written is added to the end of the file. If the file does not
- exists, it is created.
-
- 'fileName' is a filename and CANNOT be a simple device such as NIL:, a
- window specification such as CON: or RAW:, or "*".
-
- 'bufferSize' specifies the size of the IO buffer to use. There are
- in fact two buffers allocated, each of roughly (bufferSize/2) bytes
- in size. The actual buffer size use can vary slightly as the size
- is rounded to speed up DMA.
-
- If the file cannot be opened for any reason, the value returned
- will be NULL, and a secondary error code will be available by
- calling the routine dos.library/IoErr().
-
- INPUTS
- name - name of the file to open
- accessMode - one of MODE_READ, MODE_WRITE, or MODE_APPEND
- bufferSize - size of IO buffer to use. 8192 is recommended as it
- provides very good performance for relatively little
- memory.
-
- RESULTS
- file - an async file handle or NULL for failure. You should not access
- the fields in the AsyncFile structure, these are private to the
- async IO routines. In case of failure, dos.library/IoErr() can
- give more information.
-
- SEE ALSO
- CloseAsync(), dos.library/Open()
-
-
- asyncio/ReadAsync asyncio/ReadAsync
-
- NAME
- ReadAsync -- read bytes from an async file.
-
- SYNOPSIS
- actualLength = ReadAsync(file,buffer,numBytes);
-
- LONG ReadAsync(struct AsyncFile *file, APTR buffer, LONG numBytes);
-
- FUNCTION
- Read() reads bytes of information from an opened async file
- into the buffer given. 'numBytes' is the number of bytes to read from
- the file.
-
- The value returned is the length of the information actually read.
- So, when 'actualLength' is greater than zero, the value of
- 'actualLength' is the the number of characters read. Usually
- ReadAsync() will try to fill up your buffer before returning. A value
- of zero means that end-of-file has been reached. Errors are indicated
- by a value of -1.
-
- INPUTS
- file - opened file to read, as obtained from OpenAsync()
- buffer - buffer where to put bytes read
- numBytes - number of bytes to read into buffer
-
- RESULT
- actualLength - actual number of bytes read, or -1 if an error. In
- case of error, dos.library/IoErr() can give more
- information.
-
- SEE ALSO
- OpenAsync(), CloseAsync(), WriteAsync(), ReadCharAsync(),
- dos.library/Read()
-
-
-
- asyncio/ReadCharAsync asyncio/ReadCharAsync
-
- NAME
- ReadCharAsync -- read a single byte from an async file.
-
- SYNOPSIS
- byte = ReadCharAsync(file);
-
- LONG ReadCharAsync(struct AsyncFile *file);
-
- FUNCTION
- This function reads a single byte from an async file. The byte is
- returned, or -1 if there was an error reading, or if the end-of-file
- was reached.
-
- INPUTS
- file - opened file to read from, as obtained from OpenAsync()
-
- RESULT
- byte - the byte read, or -1 if no byte was read. In case of error,
- dos.library/IoErr() can give more information.
-
- SEE ALSO
- OpenAsync(), CloseAsync(), WriteCharAsync(), ReadAsync()
- dos.library/Read()
-
-
-
- asyncio/WriteAsync asyncio/WriteAsync
-
- NAME
- WriteAsync -- write data to an async file.
-
- SYNOPSIS
- actualLength = WriteAsync(file,buffer,numBytes);
-
- LONG WriteAsync(struct AsyncFile *file, APTR buffer, LONG numBytes);
-
- FUNCTION
- WriteAsync() writes bytes of data to an opened async file. 'numBytes'
- indicates the number of bytes of data to be transferred. 'buffer'
- points to the data to write. The value returned is the length of
- information actually written. So, when 'numBytes' is greater than
- zero, the value of 'numBytes' is the number of characters written.
- Errors are indicated by a value of -1.
-
- INPUTS
- file - an opened file, as obtained from OpenAsync()
- buffer - address of data to write
- numBytes - number of bytes to write to the file
-
- RESULT
- actualLength - number of bytes written, or -1 if error. In case
- of error, dos.library/IoErr() can give more
- information.
-
- SEE ALSO
- OpenAsync(), CloseAsync(), ReadAsync(), WriteCharAsync(),
- dos.library/Write
-
-
-
-
- asyncio/WriteCharAsync asyncio/WriteCharAsync
-
- NAME
- WriteCharAsync -- write a single byte to an async file.
-
- SYNOPSIS
- result = WriteCharAsync(file,byte);
-
- LONG WriteCharAsync(struct AsyncFile *, UBYTE byte);
-
- FUNCTION
- This function write a single byte to an async file.
-
- INPUTS
- file - an opened async file, as obtained from OpenAsync()
- byte - byte of data to add to the file
-
- RESULT
- result - 1 if the byte was written, -1 if there was an error. In
- case of error, dos.library/IoErr() can give more information.
-
- SEE ALSO
- OpenAsync(), CloseAsync(), ReadAsync(), WriteCharAsync(),
- dos.library/Write
-
-
-